﻿#include "PLCClientBase.h"
#include <QTimerEvent>

#pragma execution_character_set("utf-8")
QMap<ComState, QString> PLCClientBase::mapPLCStateText{
                                                       {CS_Invalid,("<font color=\'red\'>不可用</font>")},
                                                       {CS_Connected,("<font color=\'green\'>连接成功</font>")},
                                                       {CS_UnConnected,("<font color=\'yellow\'>断开连接</font>")}
};
QMap<PLCClientType, QString> PLCClientBase::mapPLCClientTypeText{
    {PCT_ModbusTcp,("ModbusTcp")},
    {PCT_ModbusRtu,("ModbusRtu")},
    {PCT_MC,("MC")},
    {PCT_FX,("FX")},
    {PCT_FinsTcp,("FinsTcp")},
    {PCT_FinsUdp,("FinsUdp")},
    {PCT_HostLink,("HostLink")},
    {PCT_TaiDa,("TaiDa")},
    {PCT_WeiKong,("WeiKong")},
    {PCT_SerialRelay,("SerialRelay")},
    {PCT_TcpRelay,("TcpRelay")}
};

PLCClientBase::PLCClientBase(QString name, QObject *parent):QObject(parent),
    mName(name)
{
#if QT_VERSION >= 0x060000
// Qt 6 的代码
#else
    // Qt 5 的代码
    qRegisterMetaTypeStreamOperators<SerialComConfig>("SerialComConfig");//注册结构体的操作流,就是重写的输入输出流
    qRegisterMetaTypeStreamOperators<TcpComConfig>("TcpClientConfig");//注册结构体的操作流,就是重写的输入输出流
    qRegisterMetaTypeStreamOperators<UdpComConfig>("UdpClientConfig");//注册结构体的操作流,就是重写的输入输出流
    qRegisterMetaTypeStreamOperators<ComClientConfig>("ComClientConfig");//注册结构体的操作流,就是重写的输入输出流
    qRegisterMetaTypeStreamOperators<PLCClientConfig>("PLCClientConfig");
#endif


    qRegisterMetaType<SerialComConfig>("SerialComConfig");
    qRegisterMetaType<SerialComConfig>("SerialComConfig&");

    qRegisterMetaType<TcpComConfig>("TcpClientConfig");
    qRegisterMetaType<TcpComConfig>("TcpClientConfig&");

    qRegisterMetaType<UdpComConfig>("UdpClientConfig");
    qRegisterMetaType<UdpComConfig>("UdpClientConfig&");

    qRegisterMetaType<ComClientConfig>("ComClientConfig");
    qRegisterMetaType<ComClientConfig>("ComClientConfig&");

    qRegisterMetaType<PLCRequestData>("PLCRequestData");
    qRegisterMetaType<PLCRequestData>("PLCRequestData&");

    qRegisterMetaType<PLCClientConfig>("PLCClientConfig");
    qRegisterMetaType<ComState>("ComState");
    setPLCState(CS_Invalid);
    mConfig.name = name;
}

PLCClientBase::~PLCClientBase()
{
}

void PLCClientBase::onInit()
{
    mLstRequestData.clear();
    initCom();
    initTimer();
}

void PLCClientBase::onQuit()
{
    if(mProcessRequestTimerID != -1)
        killTimer(mProcessRequestTimerID);
    if(mReadTimerID != -1)
        killTimer(mReadTimerID);
    if(mReconnectTimerID != -1)
        killTimer(mReconnectTimerID);
    deleteLater();
}

void PLCClientBase::onRead(const PLCRequestData &data)
{
    mLstRequestData << data;

}

void PLCClientBase::onWrite(const PLCRequestData &data)
{
    mLstRequestData << data;
}

void PLCClientBase::reconnect()
{
    onInit();
}
void PLCClientBase::setConfig(const PLCClientConfig &plcConfig)
{
    mConfig = plcConfig;
    onInitReadConfig();
}


void PLCClientBase::initTimer()
{
    mProcessRequestTimerID = startTimer(mConfig.writeSpace);
    if(mConfig.isReadConstant){
        mReadTimerID = startTimer(mConfig.readSpace);
    }
}
void PLCClientBase::stopTimer()
{
    if(mProcessRequestTimerID != -1){
        killTimer(mProcessRequestTimerID);
        mProcessRequestTimerID = -1;
    }
    if(mReadTimerID != -1){
        killTimer(mReadTimerID);
        mReadTimerID = -1;
    }
}
void PLCClientBase::onPLCConfigChanged(const PLCClientConfig &plcConfig)
{
    if(plcConfig.name != mConfig.name)
        return;
    mConfig = plcConfig;
    onInit();
    onInitReadConfig();
}

void PLCClientBase::setPLCState(const ComState &state)
{
    if(mPLCState == state)
        return;
    mPLCState = state;
    emit sigStateChanged(mPLCState);
    onStateChanged(mPLCState);
}

void PLCClientBase::onProcessRequestData()
{
    if(mLstRequestData.empty())
        return;
    PLCRequestData request = mLstRequestData.takeFirst();
    switch(request.requestType){
    case PRT_Read:
        sendReadData(request);
        break;
    case PRT_Write:
        sendWriteData(request);
        break;
    }
}

void PLCClientBase::timerEvent(QTimerEvent *event)
{
    int tempID = event->timerId();
    if(tempID == mProcessRequestTimerID){
        onProcessRequestData();
    }else if(tempID == mReadTimerID){
        QStringList lstKey = mConfig.mapReadCfgs.keys();
        std::for_each(lstKey.begin(), lstKey.end(), [&](const QString& key){
            if(mConfig.mapReadCfgs.contains(key)){
                onRead(mConfig.mapReadCfgs.value(key));
            }
        });
    }else if(tempID == mReconnectTimerID){
        reconnect();
    }
    QObject::timerEvent(event); // 将事件传递给父类处理
}

void PLCClientBase::onStateChanged(const ComState &state)
{
    if(state == CS_Connected){
        if(mReconnectTimerID != -1){
            killTimer(mReconnectTimerID);
            mReconnectTimerID = -1;
            initTimer();
        }
    } else if(state == CS_UnConnected){
        if(mReconnectTimerID != -1){
            killTimer(mReconnectTimerID);
            mReconnectTimerID = -1;
        }
        mReconnectTimerID = startTimer(2000);
        stopTimer();
    }
}
